﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using ZxZOnlineExam.IRepository;
using ZxZOnlineExam.Models;

namespace ZxZOnlineExam.Repository
{
    public class BaseEntityRepository<T> : IBaseEntityRepository<T> where T:BaseEntity,new()
    {
        private readonly DbContext _dbContext;

        /// <summary>
        /// 在构造函数中传入DbContext                                                                                        
        /// </summary>
        public BaseEntityRepository(DbContext dbContext)
        {
            this._dbContext = dbContext;
        }

        public async Task<bool> CreateAsync(T t)
        {
            _dbContext.Set<T>().Add(t);
            return await _dbContext.SaveChangesAsync()>0;
        }

        public async Task<bool> FakeDeleteAsync(Guid id)
        {
            //假删除的实现方法为：找到指定对象，将其isRemoved改为True
            if (!(await IsExsitedAsync(id)))
            {
                throw new NullReferenceException("未找到指定对象");
            }
            var result = await GetSingleAsync(id);
            result.IsRemoved = true;
            return await UpdateAsync(result);
        }

        public virtual async Task<IEnumerable<T>> GetAsync()
        {
            return await _dbContext.Set<T>().Where(t=>t.IsRemoved==false).ToListAsync();
        }

        public virtual async Task<IEnumerable<T>> GetAsync(bool asc)
        {
            var result = _dbContext.Set<T>().Where(t => t.IsRemoved == false).AsQueryable();
            if (asc)
            {
                result = result.OrderBy(t => t.CreateTime);
            }
            else
            {
                result = result.OrderByDescending(t => t.CreateTime);
            }
            return await result.ToListAsync();
        }

        public virtual async Task<IEnumerable<T>> GetAsync(int pageIndex, int pageSize = 10)
        {
            var result = _dbContext.Set<T>().Where(t => t.IsRemoved == false).AsQueryable();
            return await result.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
        }

        public virtual async Task<IEnumerable<T>> GetAsync(Expression<Func<T, bool>> expression)
        {
            var result = _dbContext.Set<T>().Where(t => t.IsRemoved == false).AsQueryable();
            result = result.Where(expression);
            return await result.ToListAsync();
        }

        public virtual async Task<IEnumerable<T>> GetAsync(Expression<Func<T, bool>> expression, bool asc)
        {
            var result = _dbContext.Set<T>().Where(t => t.IsRemoved == false).AsQueryable();
            if (asc)
            {
                result = result.OrderBy(t => t.CreateTime);
            }
            else
            {
                result = result.OrderByDescending(t => t.CreateTime);
            }
            result = result.Where(expression);
            return await result.ToListAsync();
        }

        public virtual async Task<IEnumerable<T>> GetAsync(Expression<Func<T, bool>> expression, bool asc, int pageIndex, int pageSize = 10)
        {
            var result = _dbContext.Set<T>().Where(t => t.IsRemoved == false).AsQueryable();
            if (asc)
            {
                result = result.OrderBy(t => t.CreateTime);
            }
            else
            {
                result = result.OrderByDescending(t => t.CreateTime);
            }
            result = result.Where(expression);
            return await result.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
        }

        public virtual async Task<T> GetSingleAsync(Guid id)
        {
            var result = _dbContext.Set<T>().Where(t => t.IsRemoved == false).AsQueryable();
            return await result.Where(t => t.Id == id).FirstOrDefaultAsync();
        }

        public async Task<int> GetTotalAsync()
        {
            return await _dbContext.Set<T>().CountAsync();
        }

        public async Task<bool> IsExsitedAsync(Guid id)
        {
            return await _dbContext.Set<T>().Where(t => t.IsRemoved == false).AnyAsync(t=>t.Id==id);
        }

        public async Task<bool> RealDeleteAsync(Guid id)
        {
            if (await IsExsitedAsync(id))
            {
                var result = await GetSingleAsync(id);
                _dbContext.Set<T>().Remove(result);
                return await SaveChangesAsync();
            }
            throw new NullReferenceException("未找到指定对象");
        }

        public async Task<bool> SaveChangesAsync()
        {
            if (await _dbContext.SaveChangesAsync()>0)
            {
                return true;
            }
            return false;
        }

        public async Task<bool> UpdateAsync(T t)
        {
            if (!(await IsExsitedAsync(t.Id)))
            {
                throw new NullReferenceException("未找到指定对象");
            }
            _dbContext.Set<T>().Update(t);
            return await SaveChangesAsync();
        }
    }
}
